#include <windows.h>
#include <stdio.h>
#include <iostream>
#include "mailsend.h"
#include "settings.h"
#include "base64.h"
#include <time.h>

#pragma comment(lib, "Ws2_32.lib")

#define BUFSIZE     65535
#define WAIT_TIME   500

void addLog(const char *msg)
{
#ifdef _DEBUG
    FILE *file = fopen(SMTPLog, "a+");
    fputc('\n', file);
    time_t t = time(NULL);
    fputs(ctime(&t), file);
    fputs(msg, file);
    fclose(file);
#endif
}

#ifdef SEND_TO_MAIL

int MailIt (char *mailserver, char *emailto, char *emailfrom, 
            char *emailsubject, char *emailmessage) 
{
    SOCKET               sockfd;
    WSADATA              wsaData;
    int                  bytesSent;     /* Sock FD */
    struct hostent       *host;         /* info from gethostbyname */
    struct sockaddr_in   dest_addr;     /* Host Address */
    int                  MAX_MESSAGE_SIZE =  strlen(emailmessage) + BUFSIZE*2;
    char *message =      new char[MAX_MESSAGE_SIZE];
    char *recvBuf =      new char[BUFSIZE + 1];

    if (WSAStartup(0x202, &wsaData) == SOCKET_ERROR) 
    {
        addLog("WSAStartup failed");
        WSACleanup();
		delete [] message;
		delete [] recvBuf;
        return -1;
    }
    if ((host = gethostbyname(mailserver)) == NULL) 
    {
        perror("gethostbyname");
        addLog("gethostbyname failed");
		delete [] message;
		delete [] recvBuf;
        return -1;
    }
    memset(&dest_addr, 0, sizeof(dest_addr));
    memcpy(&(dest_addr.sin_addr), host->h_addr, host->h_length);

    /* Prepare dest_addr */
    dest_addr.sin_family = host->h_addrtype;  /* AF_INET from gethostbyname */
    dest_addr.sin_port = htons(25); /* PORT defined above */

    /* Get socket */

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 
    {
        perror("socket");
        addLog("socket failed");
		delete [] message;
		delete [] recvBuf;
        return -1;
    }
    /* Connect !*/
    addLog("Connecting...");

    if (connect(sockfd, (struct sockaddr *)&dest_addr,sizeof(dest_addr)) == -1)
    {
        perror("connect");
        addLog("Connect failed");
		delete [] message;
		delete [] recvBuf;
        return -1;
    }

    Sleep(WAIT_TIME);

    bytesSent = recv(sockfd, recvBuf, BUFSIZE, 0);
    if (bytesSent > 0)
        recvBuf[bytesSent] = '\0';
    addLog(recvBuf);

    strcpy(message, "EHLO server\n");
    addLog(message);
    bytesSent = send(sockfd, message, strlen(message), 0);

    Sleep(WAIT_TIME);

    bytesSent = recv(sockfd, recvBuf, BUFSIZE, 0);
    if (bytesSent > 0)
        recvBuf[bytesSent] = '\0';
    addLog(recvBuf);

    Sleep(WAIT_TIME);

    strcpy(message, "AUTH LOGIN\n");
    addLog(message);
    bytesSent = send(sockfd, message, strlen(message), 0);

    char login [] = LOGIN;
    if (strlen(login))
    {
        std::string login64base = 
            base64_encode(reinterpret_cast<const unsigned char *>(login), strlen(login));
        login64base += "\n";
        addLog(login64base.c_str());
        bytesSent = send(sockfd, login64base.c_str(), login64base.size(), 0);
    }

    Sleep(WAIT_TIME);

    char password [] = PASSWORD;
    if (strlen(password))
    {
        std::string pass64base = 
            base64_encode(reinterpret_cast<const unsigned char *>(password), strlen(password));
        pass64base += "\n";
        addLog(pass64base.c_str());
        bytesSent = send(sockfd, pass64base.c_str(), pass64base.size(), 0);
    }

    Sleep(WAIT_TIME);

    strcpy(message, "MAIL FROM:<");
    strncat(message, emailfrom, strlen(emailfrom));
    strncat(message, ">\n", 3);
    addLog(message);
    bytesSent = send(sockfd, message, strlen(message), 0);

    Sleep(WAIT_TIME);

    bytesSent = recv(sockfd, recvBuf, BUFSIZE, 0);
    if (bytesSent > 0)
        recvBuf[bytesSent] = '\0';
    addLog(recvBuf);

    strcpy(message, "RCPT TO:<");
    strncat(message, emailto, strlen(emailto));
    strncat(message, ">\n", 3);
    addLog(message);
    bytesSent = send(sockfd, message, strlen(message), 0);
    
    Sleep(WAIT_TIME);
    
    bytesSent = recv(sockfd, recvBuf, BUFSIZE, 0);
    if (bytesSent > 0)
        recvBuf[bytesSent] = '\0';
    addLog(recvBuf);
    strcpy(message, "DATA\n");
    addLog(message);
    bytesSent = send(sockfd, message, strlen(message), 0);
    
    Sleep(WAIT_TIME);
    
    bytesSent = recv(sockfd, recvBuf, BUFSIZE, 0);
    if (bytesSent > 0)
        recvBuf[bytesSent] = '\0';
    addLog(recvBuf);
    
    Sleep(WAIT_TIME);
    
    strcpy(message, "To:");
    strcat(message, emailto);
    strcat(message, "\n");
    strcat(message, "From:");
    strcat(message, emailfrom);
    strcat(message, "\n");
    strcat(message, "Subject:");
    strcat(message, emailsubject);
    strcat(message, "\n");
    strcat(message, emailmessage);
    strcat(message, "\r\n.\r\n");
    addLog(message);
    bytesSent = send(sockfd, message, strlen(message), 0);
    
    Sleep(WAIT_TIME);
    
    bytesSent = recv(sockfd, recvBuf, BUFSIZE, 0);
    if (bytesSent > 0)
        recvBuf[bytesSent] = '\0';
    addLog(recvBuf);
    strcpy(message, "quit\n");
    addLog(message);
    bytesSent = send(sockfd, message, strlen(message), 0);
    
    Sleep(WAIT_TIME);
    
    bytesSent = recv(sockfd, recvBuf, BUFSIZE, 0);
    if (bytesSent > 0)
        recvBuf[bytesSent] = '\0';
    addLog(recvBuf);     

    delete [] recvBuf;
    delete [] message;

#ifdef WIN32
    closesocket(sockfd);
    WSACleanup();
#else
    close(sockfd);
#endif

    return 1;
}

#endif